<template>
  <basic-container v-loading="loading" element-loading-text="工艺路线加载中，请稍后" element-loading-spinner="el-icon-loading">
    <div class="orderroute-design">
      <div class="row-left">
        <el-card class="box-card">
          <div slot="header" class="clearfix">
            <span class="titles">工站库</span>
            <i class="el-icon-arrow-left" @click="shrinkStationList"></i>
          </div>
          <palette-list :sections="sections"></palette-list>
        </el-card>
      </div>
      <div class="row-center">
        <el-card class="box-card">
          <!-- 设计器顶部菜单信息 -->
          <designer-top-menu
            ref="topMenu"
            @saveDesigner="saveDesigner"
            @handleChangeThumbnail="handleChangeThumbnail"
            @handleAutoLayout="handleAutoLayout"
            @handleChangeStep="handleChangeStep"
          ></designer-top-menu>
          <!-- 设计器顶部描述信息 -->
          <designerHeader :isGdEditorPage="isGdEditorPage" :productData="productData" @changeProcess="changeProcess"></designerHeader>
          <el-row class="designer-box" :style="{ height: designerBoxHeight }">
            <el-col :span="19" class="designer-div">
              <el-card>
                <!-- 设计框 -->
                <div class="flow-div" id="myFlowDesignerDiv" :style="{ height: designerBoxHeight }"></div>
                <!-- 上下文菜单 -->
                <div id="contextMenu" class="contextMenu-con">
                  <ul class="contextMenu-list">
                    <li id="delete" @click="cxcommand($event, 'delete')">
                      <a>
                        <i class="el-icon-close"></i>
                        <span class="text"> 删除</span>
                      </a>
                    </li>
                  </ul>
                </div>
              </el-card>
              <div id="overviewSpan" v-if="thumbnail"></div>
            </el-col>
            <el-col :span="5" class="attr-div">
              <!-- 右侧面板 工站信息 -->
              <workStationInfo
                v-if="routeTypes && routeTypes.length > 0"
                ref="workStationInfo"
                :designer="_designer"
                :readOnlyPage="readOnlyPage"
                :designerBoxHeight="designerBoxHeight"
                :sections="sections"
                :routeTypes="routeTypes"
                :productData="productData"
                :productProcessId="productProcessId"
                :lineInspectionJson="lineInspectionJson"
                @submitProcessMaterialControlList="submitProcessMaterialControlList"
              ></workStationInfo>
            </el-col>
          </el-row>
        </el-card>
      </div>
      <el-dialog title="编辑原因" custom-class="orderrouteEditCauseDialog" :visible.sync="editCauseDialog.visible" append-to-body @close="handleCauseClose">
        <avue-form ref="causeform" v-model="editCauseDialog.form" :option="editCauseDialog.option" @submit="handleSubmit">
          <template slot-scope="{ disabled, size }" slot="tips">
            <div class="tips">1.该工单已生产，此时变更工艺路线会导致部分数据异常，请保存后到【产品状态】中对产品序列号状态进行调整。</div>
            <div class="tips">2.如改动涉及工单用料变更，请保存后前往【工单用料配置】修改。</div>
          </template>
          <template slot-scope="{ disabled, size }" slot="tipsLabel">
            <div class="tips">提示：</div>
          </template>
        </avue-form>
        <span slot="footer" class="dialog-footer">
          <el-button type="primary" size="small" @click="dialogSubmit"><i class="el-icon-circle-check"></i><span>保存</span> </el-button>
          <el-button size="small" @click="editCauseDialog.visible = false"><i class="el-icon-circle-close"></i><span>取消</span></el-button>
        </span>
      </el-dialog>
    </div>
  </basic-container>
</template>
<script>
import workStationInfo from './workStationInfo.vue'; //工站库设计器 右侧 工站信息 ;
import designerHeader from './designerHeader.vue'; //工站库设计器 右侧 工站信息 ;
import designerTopMenu from './designerTopMenu.vue'; //工站库设计器 顶部 菜单信息 ;
import paletteList from './paletteList.vue';
import {
  initStationInfo,
  goDesigner,
  getFlowData,
  verifySectionOrder,
  hasRepeatNodeFn,
  verifyNodeFn,
  verifyStationFn,
  resetOrder,
  checkArrayRepeatData,
  returnNodeInfoList
} from './designer';
import { go } from '@/assets/js/go';
import { guid } from '@/util/helpers';
import { defaultData, defaultStartAndEndNodeData } from './palette';
import { getWorkstation, processSubmit, processWoSubmit, getSectionByPartId } from '@/api/product/productrouteManage';
import { mapState } from 'vuex';
import { getDictionary } from '@/api/system/dict';
let G = go.GraphObject.make; //GOJS对象
let _myContextMenu = {};
export default {
  components: {
    workStationInfo,
    designerHeader,
    designerTopMenu,
    paletteList
  },
  inject: ['reload'],
  data() {
    return {
      activeNames: '',
      changeProcessFlag: false, // 是否切换所有工艺路线
      processMaterialControlList: [], //工艺路线 物料信息
      loading: true,
      routeTypes: [],
      sections: [], // 产品对应工段列表
      _designer: null,
      isAlreadyConfig: false, // 是否已配置过工艺路线
      defaultData, // 开始，结束两个节点
      productData: {}, // 产品工艺路线详情
      designerBoxHeight: `calc(100vh - 220px)`, // 设计器区域高度
      paletteData: [], //左侧控件数据
      processObj: {},
      thumbnail: true,
      workSectionData: [], //工段下拉数据
      mainParams: null,
      editCauseDialog: {
        visible: false,
        form: {},
        option: {
          submitBtn: false,
          emptyBtn: false,
          column: [
            {
              prop: 'reason',
              label: '编辑原因',
              type: 'textarea',
              span: 24,
              minRows: 5,
              maxRows: 5,
              type: 'textarea',
              maxlength: 300,
              showWordLimit: true
            },
            {
              prop: 'tips',
              label: '提示',
              span: 24,
              labelslot: true,
              formslot: true
            }
          ]
        }
      },
      productProcessId: '',
      lineInspectionJson: []
    };
  },
  computed: {
    ...mapState({
      currentStationInfo: (state) => state.design.currentStationInfo,
      allActiveStations: (state) => state.design.allActiveStations
    }),
    // 路由参数
    routeQuery() {
      return this.$route.query;
    },
    routePath() {
      return this.$route.path;
    },
    // 查看页面 只读
    readOnlyPage() {
      if (this.routePath.endsWith('pdesign') || this.routePath.endsWith('gdesign')) {
        return false;
      } else {
        return true;
      }
    },
    // 是否工单工艺路线设计器
    isGdEditorPage() {
      if (this.$route.path.endsWith('pdesign') || this.$route.path.endsWith('pread')) {
        return false;
      } else if (this.$route.path.endsWith('gdesign') || this.$route.path.endsWith('gread')) {
        return true;
      }
    },
    // 工艺路线是否已设计
    routeConfigured() {
      return Boolean(this.routeQuery.routeConfigured);
    },
    // 工单状态
    workOrderStatus() {
      return Number(this.routeQuery.status);
    }
  },
  async mounted() {
    this.init();
    this.getStationType(); // 获取工站类型
    this.calculatePageHeight(); // 动态改变页面高度;
    this.calculateDesignerBoxHeight();
  },
  destroyed() {
    this.$store.commit('design/setCurrentStationInfo', {});
    this.$store.commit('design/singleUseSetAllActiveStations', []);
    this._designer = null;
  },
  methods: {
    async init() {
      try {
        // 如果是工单工艺页面跳转进来且ID为空，则不执行getProcessDetail
        if (this.isGdEditorPage && !this.routeQuery.id) {
          this.getLeftStationData(); // 获取左侧工站库数据
          return;
        }
        // 判断是产品还是工单进入的编辑页;根据工艺路线id获取工艺路线详情
        this.productData = this.isGdEditorPage
          ? await this.$store.dispatch('design/getProcessWorkRouteByWo', { id: this.routeQuery.id })
          : await this.$store.dispatch('design/getProcessDetail', this.routeQuery.id);
        this.getLeftStationData(); // 获取左侧工站库数据
        // 设置工艺信息
        if (this.productData) {
          this.processObj['processId'] = this.productData.id;
          this.processObj['processCode'] = this.productData.code;
          this.processObj['processName'] = this.productData.name;
          if (!this.productData.originalProcessId && !this.productData.id && this.isGdEditorPage) {
            this.$message.warning('该工单未配置工单工艺路线');
          }
          if (!this.productData.firstRouteDefinitionJson) {
            this.productData.firstRouteDefinitionJson = JSON.stringify({
              lableSource: 'createSN',
              upperPartName: '',
              isImport: true,
              ruleName: '',
              upperPartNo: '',
              upperPartMasterId: '',
              ruleCode: '',
              ruleId: ''
            });
          }
          console.log(this.productData, 'this.productData.processRouteList');
          this._forEach(this.productData.processRouteList, (item) => {
            if (item.workSectionId && item.workSectionId != null) {
              let workSectionId = this._find(this.$refs.workStationInfo.workSectionData, { sectionId: item.workSectionId });
              if (workSectionId) {
                item.workSectionId = this._cloneDeep(JSON.stringify(workSectionId));
              } else {
                item.workSectionId = this._cloneDeep(item.workSectionId);
              }
            }
          });
          this.lineInspectionJson = JSON.parse(this.productData.lineInspectionJson || '[]');
        } else {
          console.warn('未能获取工艺路线详情');
        }
      } catch (error) {
        this.loading = false;
      }
    },
    async getLeftStationData() {
      let that = this;
      let sectionResult = await getSectionByPartId(this.$route.query.partMasterId);
      let sectionData = sectionResult.data.data;
      if (sectionData && sectionData.sections.length > 0) {
        that.sections = sectionData.sections.map((item) => {
          return {
            sectionSequence: item.sectionSequence,
            sectionName: item.sectionName,
            sectionCode: item.sectionCode,
            sectionId: item.sectionId,
            workSectionColor: item.sectionColor,
            routes: []
          };
        });
      }

      // 获取工站库信息
      let result = await getWorkstation();
      if (result && result.status == 200) {
        let data = result.data.data;
        that.paletteData = [];
        this._forEach(data, (item) => {
          if (this.$route.query.routeConfigured == false) {
            if (item.status != 0) {
              that.paletteData.push(item);
            }
          } else {
            that.paletteData.push(item);
          }
        });
        for (let i = 0; i < that.paletteData.length; i++) {
          that.paletteData[i].category = that.paletteData[i].id;
          that.paletteData[i].key = guid();
          that.paletteData[i].code = that.paletteData[i].code;
          that.paletteData[i].routeType = that.paletteData[i].type;
          that.paletteData[i].text = that.paletteData[i].name;
          that.paletteData[i].name = that.paletteData[i].name;
          that.paletteData[i].imgsrc = that.paletteData[i].imgsrc;
          // that.paletteData[i].workSectionName = that.paletteData[i].sectionName;
          delete that.paletteData[i].options;
          for (let j = 0; j < that.sections.length; j++) {
            if (that.sections[j].sectionId == that.paletteData[i].sectionId) {
              that.paletteData[i].workSectionId = that.sections[j].sectionId;
              that.paletteData[i].workSectionName = that.sections[j].sectionName;
              that.paletteData[i].workSectionColor = that.sections[j].workSectionColor;
              that.sections[j].routes.push(that.paletteData[i]);
            }
          }
        }
        that.paletteData = await that.defaultData.concat(that.paletteData); // 拼接 开始结束节点
        console.log(that.sections, 'that.sections', that.paletteData);
        that.initDesigner('myFlowDesignerDiv', that.paletteData); // 初始化流程设计器
        //  初始化 左侧工站库(列数)
        for (let i = 0; i < that.sections.length; i++) {
          that.sections[i].routes.sort((a, b) => {
            if (a.workSectionWorkstationSequence === null) return 1;
            if (b.workSectionWorkstationSequence === null) return -1;
            return a.workSectionWorkstationSequence - b.workSectionWorkstationSequence;
          });
          that.initLeftStations('myPaletteDiv' + i, that.sections[i].routes);
        }
      }
    },
    // 渲染流程图 isGdEditorPage:是否工单工艺
    renderFlow(productData, isGdEditorPage = false) {
      let that = this;
      let routeJson = {};
      let processRouteList = isGdEditorPage ? productData.processRouteVOList : productData.processRouteList;
      if (productData.routeJson && productData.routeJson != null) {
        routeJson = JSON.parse(productData.routeJson || '{}');
        if (routeJson.nodeDataArray) {
          this._forEach(routeJson.nodeDataArray, (item) => {
            for (let i = 1; i <= 8; i++) {
              item[`circle${i}Visible`] = false;
              item[`rectVisible`] = false;
              item[`workSectionColor`] = 'rgba(0, 0, 0, 0)';
            }
            delete item.options;
          });
        }
        console.log(routeJson.nodeDataArray, 'routeJson.nodeDataArray');
        if (processRouteList && processRouteList.length > 0) {
          that.isAlreadyConfig = true; //
          processRouteList.map((p) => {
            routeJson.nodeDataArray
              .filter((n) => n.key != 'Start' && n.key != 'End')
              .map((r) => {
                if ((r.workstationId && p.workstationId == r.workstationId) || (r.id && p.workstationId == r.id)) {
                  p.key = r.key;
                  r.rectVisible = true;
                  r.workSectionColor = p.workSectionColor;
                  r.circle1Visible = p.isFirst;
                  r.circle2Visible = !p.isFirst;
                  r.circle3Visible = p.isFirstInSection;
                  r.circle4Visible = !p.isFirstInSection;
                  r.circle5Visible = p.isLastInSection;
                  r.circle6Visible = !p.isLastInSection;
                  r.circle7Visible = p.isLast;
                  r.circle8Visible = !p.isLast;
                }
              });
          });
          console.log('processRouteList', processRouteList);
          that.$store.commit('design/singleUseSetAllActiveStations', processRouteList);
        } else {
          that.isAlreadyConfig = false; // 未配置完成
          routeJson = null;
        }
      } else {
        // 没有routeJson => 处理工艺路线导入问题
        routeJson = {
          class: 'GraphLinksModel',
          modelData: {
            position: '-650 -150'
          },
          nodeDataArray: [
            {
              key: 'Start',
              text: '开始',
              category: 'Start',
              imgsrc: '/img/order-route/1.png',
              location: '-650 -150',
              attributes: ''
            }
          ],
          linkDataArray: []
        };
        // 有processRouteList时处理逻辑
        if (processRouteList && processRouteList.length > 0) {
          that.isAlreadyConfig = true;
          console.log('没有routeJson', processRouteList);
          let nodeDataArray = that._map(processRouteList, (item, index) => {
            delete item.options;
            item.category = String(item.workstationId);
            item.key = guid();
            item.text = item.name || item.routeName;
            let nodeObj = this._find(that.paletteData, { name: item.name });
            if (nodeObj) {
              item.imgsrc = nodeObj.imgsrc;
            }
            item.options = '';
            let location = [-520 + 130 * index, -150];
            return {
              ...item,
              location: location.join(' ')
            };
          });

          routeJson.nodeDataArray = [...routeJson.nodeDataArray, ...nodeDataArray];
          let endLocation = [-520 + 130 * processRouteList.length, -150];
          routeJson.nodeDataArray.push({
            key: 'End',
            text: '结束',
            category: 'End',
            imgsrc: '/img/order-route/5.png',
            location: endLocation.join(' '),
            attributes: ''
          });
          for (let i = 0; i < routeJson.nodeDataArray.length - 1; i++) {
            routeJson.linkDataArray.push({
              from: routeJson.nodeDataArray[i].key,
              to: routeJson.nodeDataArray[i + 1].key
            });
          }
          if (routeJson.nodeDataArray) {
            this._forEach(routeJson.nodeDataArray, (item) => {
              for (let i = 1; i <= 8; i++) {
                item[`circle${i}Visible`] = false;
                item[`rectVisible`] = false;
                item[`workSectionColor`] = item[`workSectionColor`] || 'rgba(0, 0, 0, 0)';
              }
            });
          }
          processRouteList.map((p) => {
            routeJson.nodeDataArray
              .filter((n) => n.key != 'Start' && n.key != 'End')
              .map((r) => {
                if ((r.workstationId && p.workstationId == r.workstationId) || (r.id && p.workstationId == r.id)) {
                  p.key = r.key;
                  p.options = '';
                  r.rectVisible = true;
                  r.workSectionColor = p.workSectionColor || 'rgba(0, 0, 0, 0)';
                  r.circle1Visible = p.isFirst;
                  r.circle2Visible = !p.isFirst;
                  r.circle3Visible = p.isFirstInSection;
                  r.circle4Visible = !p.isFirstInSection;
                  r.circle5Visible = p.isLastInSection;
                  r.circle6Visible = !p.isLastInSection;
                  r.circle7Visible = p.isLast;
                  r.circle8Visible = !p.isLast;
                }
              });
          });
          console.log('processRouteList', processRouteList);
          that.$store.commit('design/singleUseSetAllActiveStations', processRouteList);
        } else {
          that.isAlreadyConfig = false; // 未配置完成
          routeJson = null;
        }
      }
      console.log('that.allActiveStations', that.allActiveStations);
      that.displayFlow(routeJson, that.allActiveStations);
    },
    //  初始化流程设计器
    initDesigner(divId, myPaletteData) {
      this._designer = goDesigner({ dom: divId, isReadOnly: this.readOnlyPage });
      let designer = this._designer.designer;
      // 监听节点删除事件
      designer.commandHandler.canDeleteSelection = function () {
        return designer.selection.all(function (nodeOrLink) {
          //开始结束节点不允许删除
          if (nodeOrLink.data.key == 'Start' || nodeOrLink.data.key == 'End') {
            return false;
          } else {
            return true;
          }
        });
      };
      G(go.Overview, 'overviewSpan', { observed: designer });
      // 工艺路线上切换工站双击事件
      designer.addDiagramListener('ObjectDoubleClicked', (ev) => {});
      //删除选中工站事件
      designer.addDiagramListener('SelectionDeleted', (ev) => {
        this.$store.commit('design/removeAllActiveStations', this.currentStationInfo);
        this.$store.commit('design/setCurrentStationInfo', {});
      });
      //工艺路线上切换选择工站事件
      designer.addDiagramListener('ChangedSelection', (ev) => {});
      //工艺路线上单击事件
      designer.addDiagramListener('ObjectSingleClicked', (ev) => this.handleNodeClcik(ev));
      //工艺路线上右击事件
      designer.addDiagramListener('ObjectContextClicked', (ev) => this.handleNodeClcik(ev));
      //不在任何部分的单击
      designer.addDiagramListener('BackgroundSingleClicked', (ev) => this.handleNodeClcik(ev, 'blank'));
      //拖放节点到这个图表中时事件
      designer.addDiagramListener('ExternalObjectsDropped', (event) => {
        event.subject.each((part) => {
          let currentStationInfo = initStationInfo(part.data);
          console.log(currentStationInfo, 'currentStationInfo');
          this.setNodeColor(currentStationInfo);
          this.$store.commit('design/setCurrentStationInfo', currentStationInfo);
          this.$store.commit('design/setAllActiveStations', currentStationInfo);
        });
        // 展开任何“宏”
        designer.commandHandler.ungroupSelection();
      });

      var contextMenuElement = document.getElementById('contextMenu');
      _myContextMenu = G(go.HTMLInfo, {
        show: showContextMenu,
        mainElement: contextMenuElement
      });
      if (contextMenuElement) {
        //上下文点击事件
        contextMenuElement.addEventListener(
          'contextmenu',
          function (e) {
            e.preventDefault();
            return false;
          },
          false
        );
      }
      //遍历模板数据生成中间设计框
      for (var i = 0; i < myPaletteData.length; i++) {
        if (!myPaletteData[i].imgsrc) {
          myPaletteData[i].imgsrc = '/img/flow-design/过站.png';
        }
        designer.nodeTemplateMap.add(myPaletteData[i].category, this.makeNodeTemplate(myPaletteData[i].imgsrc, this.paletteData[i].key));
      }
      // 流程连接线的样式模板
      designer.linkTemplate = this.makeLinkTemplate();
      designer.contextMenu = _myContextMenu;
      function showContextMenu(obj, diagram, tool) {
        var cmd = diagram.commandHandler;
        // 根据当前选中节点是否有该方法判断是否显示
        document.getElementById('delete').style.display = cmd.canDeleteSelection() ? 'block' : 'none';
        contextMenuElement.style.display = 'block';
        if (obj && obj.data && obj.data.key) {
          if (obj.data.key == 'Start' || obj.data.key == 'End') {
            contextMenuElement.style.display = 'none';
          }
        }

        var mousePt = diagram.lastInput.viewPoint;
        // 让上下文菜单在X轴增加195px宽度是因为.designer-con容器有一个padding-left为195px的左内边距
        contextMenuElement.style.left = mousePt.x + 35 + 'px';
        contextMenuElement.style.top = mousePt.y + 'px';
      }
      this.renderFlow(this.productData, this.isGdEditorPage); // 渲染流程图
    },
    // 初始化左侧工站库
    initLeftStations(div, myPaletteData) {
      let myPalette = G(go.Palette, div, {
        layout: G(go.GridLayout, {
          sorting: go.GridLayout.Forward,
          cellSize: new go.Size(1, 1),
          wrappingColumn: 2, // 工站库列数
          isViewportSized: true
        })
      });
      for (var i = 0; i < myPaletteData.length; i++) {
        if (!myPaletteData[i].imgsrc) {
          myPaletteData[i].imgsrc = '/img/flow-design/过站.png';
        }
        myPaletteData[i].rectVisible = false;
        myPaletteData[i].workSectionColor = myPaletteData[i].workSectionColor;
        myPaletteData[i].circle1Visible = false;
        myPaletteData[i].circle2Visible = false;
        myPaletteData[i].circle3Visible = false;
        myPaletteData[i].circle4Visible = false;
        myPaletteData[i].circle5Visible = false;
        myPaletteData[i].circle6Visible = false;
        myPaletteData[i].circle7Visible = false;
        myPaletteData[i].circle8Visible = false;
        myPalette.nodeTemplateMap.add(myPaletteData[i].category, this.makeNodeTemplate(myPaletteData[i].imgsrc, myPaletteData[i].key));
      }
      myPalette.model.nodeDataArray = myPaletteData;
      myPalette.nodes.each(function (node) {
        node.ports.each(function (port) {
          port.cursor = '';
        });
        node.elements.each(function (tb) {
          if (tb instanceof go.TextBlock) {
            tb.visible = true;
          }
        });
      });
    },
    // 工站单击事件，将当前点击的工站信息渲染值右侧表单中
    onObjectSingleClicked(part) {
      let { category, key } = part.data;
      // 检查是否为开始或结束节点
      if (category === 'Start' || category === 'End') {
        this.$message.warning(`开始和结束步骤不可编辑！`);
        this.setcurrentStationInfo(this.defaultData, key);
        return;
      }

      // 如果当前选中的工站信息与之前的相同，则不进行赋值
      if (this.currentStationInfo && this.currentStationInfo.key === key) {
        return;
      }

      // 如果已经配置过工艺路线，获取当前选中的工站信息并处理点击事件
      if (this.isAlreadyConfig) {
        let currentStationInfo = this.allActiveStations.find((all) => all.key == key);
        this.$store.commit('design/setCurrentStationInfo', currentStationInfo);
      }
      // 设置当前步骤信息
      this.setcurrentStationInfo(this.allActiveStations, key);
    },
    // 设置节点颜色
    setNodeColor(currentStationInfo) {
      if (currentStationInfo.workSectionId && currentStationInfo.key) {
        if (currentStationInfo.workSectionColor) {
          let color = currentStationInfo.workSectionColor;
          let data = this._designer.designer.findNodeForKey(currentStationInfo.key);
          // this._designer.designer.model.setDataProperty(data, 'background', color ? color : 'rgba(0, 0, 0, 0)');
          this._designer.designer.model.setDataProperty(data, 'workSectionColor', color ? color : 'rgba(0, 0, 0, 0)');
        }
      }
    },
    // 创建拖拽模板
    makeNodeTemplate(imgsrc, key) {
      const handleDoubleClick = (e, node) => {
        let flowData = JSON.parse(getFlowData(this._designer.designer) || '{}');
        let currentNode = this._cloneDeep(node.part.data);
        //判断是否存在相同工站
        if (this._find(flowData.nodeDataArray, { text: currentNode.text })) {
          this.$message.warning(`已经存在 ${currentNode.text} 工站，不能重复添加`);
          return;
        }
        //判断是否存在开始、结束节点
        const startNode = this._find(flowData.nodeDataArray, { text: '开始' });
        const endNode = this._find(flowData.nodeDataArray, { text: '结束' });
        if (!startNode && currentNode.text !== '开始') {
          this.$message.warning('请拖拽出开始节点！');
          return;
        }
        if (!endNode && currentNode.text !== '结束') {
          this.$message.warning('请拖拽出结束节点！');
          return;
        }
        let lastNodeLocation = flowData.nodeDataArray[flowData.nodeDataArray.length - 1].location;
        let newLocation = [Number(lastNodeLocation.split(' ')[0]) + 130, lastNodeLocation.split(' ')[1]].join(' ');
        currentNode['location'] = newLocation;
        if (currentNode.text === '开始' || currentNode.text === '结束') {
          this._designer.designer.model.addNodeData(currentNode);
        } else {
          this.addIntermediateNode(flowData, currentNode);
        }
        this.selectAndColorNode(currentNode);
      };

      return G(
        go.Node,
        'Vertical',
        {
          locationSpot: go.Spot.Center
        },
        new go.Binding('location', 'location', go.Point.parse).makeTwoWay(go.Point.stringify),
        {
          selectable: true,
          selectionAdornmentTemplate: this._designer.makeNodeSelectionAdornmentTemplate(),
          doubleClick: handleDoubleClick
        },
        G(
          go.Panel,
          'Horizontal',
          G(go.Shape, 'Circle', { width: 10, height: 10, fill: '#02A7F0', margin: 2, stroke: null }, new go.Binding('visible', 'circle1Visible')),
          G(go.Shape, 'Circle', { width: 10, height: 10, fill: '#D7D7D7', margin: 2, stroke: null }, new go.Binding('visible', 'circle2Visible')),
          G(go.Shape, 'Circle', { width: 10, height: 10, fill: '#FFFF80', margin: 2, stroke: null }, new go.Binding('visible', 'circle3Visible')),
          G(go.Shape, 'Circle', { width: 10, height: 10, fill: '#D7D7D7', margin: 2, stroke: null }, new go.Binding('visible', 'circle4Visible')),
          G(go.Shape, 'Circle', { width: 10, height: 10, fill: '#C280FF', margin: 2, stroke: null }, new go.Binding('visible', 'circle5Visible')),
          G(go.Shape, 'Circle', { width: 10, height: 10, fill: '#D7D7D7', margin: 2, stroke: null }, new go.Binding('visible', 'circle6Visible')),
          G(go.Shape, 'Circle', { width: 10, height: 10, fill: '#F59A23', margin: 2, stroke: null }, new go.Binding('visible', 'circle7Visible')),
          G(go.Shape, 'Circle', { width: 10, height: 10, fill: '#D7D7D7', margin: 2, stroke: null }, new go.Binding('visible', 'circle8Visible'))
        ),
        G(go.Picture, imgsrc, {
          width: 45,
          height: 40,
          margin: 2,
          portId: '',
          fromLinkable: key !== 'End',
          toLinkable: key !== 'Start',
          toMaxLinks: 1,
          fromMaxLinks: 1,
          cursor: 'pointer'
        }),
        G(
          go.Panel,
          'Horizontal',
          G(
            go.Shape,
            'Rectangle', // 这里使用Rectangle作为颜色小块，你也可以使用Circle等
            { width: 10, height: 10, margin: 0, stroke: null },
            new go.Binding('fill', 'workSectionColor'),
            new go.Binding('visible', 'rectVisible')
          ),
          G(
            go.TextBlock,
            '默认文本',
            {
              editable: false,
              margin: 0,
              textAlign: 'center',
              width: 78,
              maxLines: 2,
              background: '#ffffff',
              overflow: go.TextBlock.OverflowEllipsis,
              alignment: go.Spot.Center
            },
            new go.Binding('text', 'text')
          )
        ),
        {
          toolTip: this._designer.makeTooltipTemplate(),
          contextMenu: _myContextMenu
        }
      );
    },
    addIntermediateNode(flowData, currentNode) {
      const nodeData = this._filter(flowData.nodeDataArray, (item) => item.text !== '开始' && item.text !== '结束');
      this._designer.designer.model.addNodeData(currentNode);

      if (nodeData.length === 0) {
        this._designer.designer.model.addLinkData({ from: 'Start', to: currentNode.key });
      } else {
        this._designer.designer.model.addLinkData({ from: nodeData[nodeData.length - 1].key, to: currentNode.key });
        this.adjustEndNodeLocation(nodeData);
      }
      this._designer.designer.model.addLinkData({ from: currentNode.key, to: 'End' });
    },
    // 调整结束节点位置
    adjustEndNodeLocation(nodeData) {
      const endNode = this._designer.designer.findNodeForKey('End');
      this._designer.designer.startTransaction('Deleted Links');
      this._designer.designer.removeParts(endNode.findLinksConnected());
      this._designer.designer.commitTransaction('Deleted Links');

      const lastNodeLocation = nodeData[nodeData.length - 1].location;
      const newEndNodeLocation = [Number(lastNodeLocation.split(' ')[0]) + 130 * 2, lastNodeLocation.split(' ')[1]].join(' ');
      this._designer.designer.model.setDataProperty(this._designer.designer.model.findNodeDataForKey('End'), 'location', newEndNodeLocation);
    },
    // 选择和设置节点颜色
    selectAndColorNode(currentNode) {
      const nodeKey = this._designer.designer.model.findNodeDataForKey(currentNode.key);
      const selectNode = this._designer.designer.findNodeForData(nodeKey);
      this._designer.designer.select(selectNode);
      if (currentNode.workSectionId && currentNode.workSectionId !== null) {
        this.setNodeColor(currentNode);
      }
      const currentStationInfo = initStationInfo(currentNode, true);
      this.$store.commit('design/setCurrentStationInfo', currentStationInfo);
      this.$store.commit('design/setAllActiveStations', currentStationInfo);
    },
    // 定义连接线的样式模板
    makeLinkTemplate() {
      return G(
        go.Link, // the whole link panel
        {
          selectable: true,
          selectionAdornmentTemplate: this._designer.makeLinkSelectionAdornmentTemplate()
        },
        {
          relinkableFrom: true,
          relinkableTo: true,
          reshapable: true,
          resegmentable: true
        },
        {
          routing: go.Link.AvoidsNodes, // 线会自动90度转弯（AvoidsNodes自动绕开节点 Orthogonal）
          curve: go.Link.JumpGap,
          corner: 5,
          toShortLength: 4
        },
        G(
          go.Shape, // 线条
          {
            isPanelMain: true,
            stroke: '#666',
            strokeWidth: 2
          }
        ),
        G(
          go.Shape, // 箭头
          {
            toArrow: 'Standard',
            stroke: '#666'
          }
        ),
        G(
          go.Panel,
          'Auto',
          G(
            go.Shape, // 标签背景色
            {
              fill: null,
              stroke: null
            },
            new go.Binding('fill', 'pFill')
          ),
          G(
            go.TextBlock, // 标签文本
            {
              textAlign: 'center',
              font: '9pt helvetica, arial, sans-serif',
              stroke: '#000',
              margin: 2
            },
            new go.Binding('text', 'text')
          )
        )
      );
    },
    // 这是通用菜单命令
    cxcommand(event, val) {
      let contextMenuElement = document.getElementById('contextMenu');
      if (val === undefined) val = event.currentTarget.id;
      let diagram = this._designer.designer;
      switch (val) {
        case 'delete':
          diagram.commandHandler.deleteSelection();
          break;
      }
      diagram.currentTool.stopTool();
      contextMenuElement.style.display = 'none';
    },
    // 在设计面板中显示流程图
    displayFlow(flowData, allActiveStations) {
      if (!flowData) {
        flowData = structuredClone(defaultStartAndEndNodeData);
      }
      this.allActiveStations = [];
      this.isSelectRow = false;
      if (!flowData) return;
      let notLinkDataArray = this._map(flowData.linkDataArray, (item) => {
        let node;
        if (item.from === 'Start') {
          node = this._find(flowData.nodeDataArray, { key: item.to });
        } else {
          node = this._find(flowData.nodeDataArray, { key: item.from });
        }
        if (node) {
          return item;
        }
      });
      flowData.linkDataArray = this._compact(notLinkDataArray);
      if (this._designer) {
        this._designer.designer.model = go.Model.fromJson(flowData);
        let pos = this._designer.designer.model.modelData.position;
        if (pos) this._designer.designer.initialPosition = go.Point.parse(pos);
        this.currentStationInfo = {};
        this._forEach(allActiveStations, (item) => {
          let templateRuleInfo = this._get(item, 'templateRuleInfo', []);
          let templateRuleInfoString = JSON.stringify(templateRuleInfo);
          if (templateRuleInfo.length > 0 && templateRuleInfoString !== '[{}]') {
            item['templateRuleInfo'] = this._map(templateRuleInfo, (item) => {
              return {
                sequenceDefineId: item.sequencerule ? item.sequencerule.id : item.sequenceDefine ? item.sequenceDefine.id : '',
                sequenceName: item.sequencerule ? item.sequencerule.name : item.sequenceDefine ? item.sequenceDefine.name : '',
                fileManageId: item.printModal.id,
                selectPrintModels: item.printModal.name,
                customerCode: item.customer ? item.customer.code : '',
                customerName: item.customer ? item.customer.name : ''
              };
            });
          } else {
            item['templateRuleInfo'] = [];
          }
          if (item.workSectionId && item.workSectionId != null) {
            this.setNodeColor(item);
          }
        });
        this.allActiveStations = allActiveStations;
        this.loading = false;
      }
    },
    // 节点点击（单击，右击，其余部分点击）
    handleNodeClcik(ev, area) {
      // area:空白区域
      if (area) {
        this.$store.commit('design/setCurrentStationInfo', {});
      } else {
        let part = ev.subject.part;
        //当前点击元素为节点
        if (part instanceof go.Node) {
          this.onObjectSingleClicked(part);
        } else if (part instanceof go.Link) {
          // 当前点击元素为连线
          this.$store.commit('design/setCurrentStationInfo', {});
        }
      }
    },
    // 设置当前点击节点信息
    setcurrentStationInfo(data, key) {
      let selectedStationInfo = this._find(data, { key });
      if (selectedStationInfo) {
        this.$refs.workStationInfo.activeName = '1';
        let currentStationInfo = { ...selectedStationInfo };
        if (key != 'End' && key != 'Start') {
          if (currentStationInfo.processRouteConfigList && currentStationInfo.processRouteConfigList.length > 0) {
            for (let i = 0; i < currentStationInfo.processRouteConfigList.length; i++) {
              const route = currentStationInfo.processRouteConfigList[i];
              if (route.key == 'isDeduct') {
                route.value = this.$util.util.stringToBoolean(route.value);
              }
              currentStationInfo[route.key] = route.value;
            }
          }
          // 查询包装规则
          if (currentStationInfo && currentStationInfo.productPackingConfigId) {
            this.$refs.workStationInfo && this.$refs.workStationInfo.getPackWeightInfo(currentStationInfo.productPackingConfigId);
          }
        }
        console.log(currentStationInfo, '设置当前点击节点信息');
        this.$store.commit('design/setCurrentStationInfo', currentStationInfo);
      }
    },
    // 切换产品工艺路线 工艺id
    async changeProcess(id) {
      this.productProcessId = id;
      this.productData = await this.$store.dispatch('design/getProcessDetail', id);
      this.changeProcessFlag = true;
      if (this.productData) {
        this.productData.id = this.processObj.processId;
        this.productData.code = this.processObj.processCode;
        this.productData.name = this.processObj.processName;
        if (this.productData.processRouteList && this.productData.processRouteList.length > 0) {
          this.productData.processRouteList.forEach((item) => {
            delete item.id;
            item.processRouteConfigList.forEach((pItem) => {
              delete pItem.id;
              delete pItem.processRouteId;
            });
          });
        }
      }
      // 工单工艺路线设计器页面且未设计工艺路线
      if (this.isGdEditorPage && !this.routeConfigured) {
        this.productData.id = null;
      }

      this.renderFlow(this.productData); // 渲染流程图
    },
    finishCheck(msg) {
      this.$message.warning(msg);
      this.loading = false;
      return false;
    },
    // 更新节点的更新时间
    updateNodeTimes(routeJson) {
      if (routeJson.nodeDataArray && routeJson.nodeDataArray.length > 0) {
        routeJson.nodeDataArray.forEach((item) => {
          if (item.key !== 'Start' && item.key !== 'End') {
            item.updateTime = new Date().getTime();
          }
        });
      }
    },
    // 检查是否存在未连接的工站
    hasUnconnectedNodes(routeJson) {
      return routeJson.nodeDataArray.length - routeJson.linkDataArray.length !== 1;
    },
    // 处理二次保存问题
    handleDuplicateSave(nodeInfoList) {
      if (this.productData && this.productData.processRouteList) {
        if (nodeInfoList.length > 0 && this.productData.processRouteList.length > 0) {
          this.productData.processRouteList.forEach((pRoute) => {
            nodeInfoList.forEach((nRoute) => {
              if (nRoute.routeCode === pRoute.routeCode) {
                nRoute.id = pRoute.id;
              }
            });
          });
        }
      }
    },
    // 构建保存主参数
    buildMainParams(params) {
      let mainParams = {
        id: this.productData.id,
        code: this.productData.code,
        name: this.productData.name,
        productPartId: this.routeQuery.partMasterId || this.productData.partMasterId, // 产品id
        productPartNo: this.routeQuery.partNo || this.productData.partNo, // 产品编码
        productPartName: this.routeQuery.partName || this.productData.partName, // 产品名称,
        routeJson: params.routeJson,
        originalProcessId: this.productData.originalProcessId,
        lineInspectionJson: JSON.stringify(this.$refs.workStationInfo.lineInspectionList)
        // changeProcessFlag: this.changeProcessFlag,
      };
      // 追溯配置JSON
      let tracingConfigJson = this.$refs.workStationInfo.sectionAndRouteList.filter((item) => item.routeId);
      console.log(tracingConfigJson, 'tracingConfigJson');
      mainParams.tracingConfigJson = JSON.stringify(tracingConfigJson);
      // 首工序定义JSON
      let firstRouteDefinitionJson = this.$refs.workStationInfo.firstStep;
      mainParams.firstRouteDefinitionJson = JSON.stringify(firstRouteDefinitionJson);
      console.log(firstRouteDefinitionJson, 'firstRouteDefinitionJson');

      if (this.isGdEditorPage) {
        mainParams.workOrderId = this.routeQuery.workOrderId;
        mainParams.workOrderNo = decodeURI(this.routeQuery.workOrderNo);
        mainParams.processRouteDTOList = params.processRouteList;
      } else {
        // mainParams.isConfigRoute = 是否已配置工艺路线
        mainParams.isAudit = this.productData.isAudit;
        mainParams.routeConfigured = this.productData.routeConfigured;
        mainParams.processRouteList = params.processRouteList;
      }
      return mainParams;
    },
    // 保存工艺路线
    saveDesigner() {
      this.loading = true;
      //获取到整个路由路线中的数据，其中routeJson.nodeDataArray包含了自定义属性List
      let routeJson = JSON.parse(getFlowData(this._designer.designer) || '{}');
      console.log(routeJson, '画布：routeJson');
      // 更新节点的更新时间
      this.updateNodeTimes(routeJson);

      let linkDataArray = routeJson.linkDataArray;

      // 检查连线模式是否为1对多
      let linkFormArray = linkDataArray.map((node) => node.from);
      let lineModelType = checkArrayRepeatData(linkFormArray);
      if (lineModelType) {
        console.warn('1对多连线模式', routeJson);
        return this.finishCheck('目前不支持一对多配置模式，请重新进行配置');
      }

      // 检查是否存在未连接的工站
      if (this.hasUnconnectedNodes(routeJson)) {
        return this.finishCheck('存在未连接的工站，请确保所有工站正确连接后再保存');
      }

      // 验证重复工站
      if (!hasRepeatNodeFn(routeJson)) {
        this.loading = false;
        return false;
      }

      // 重置节点排列顺序
      routeJson = resetOrder(routeJson);

      // 检查工艺路线配置是否为空
      if (routeJson.linkDataArray.length == 0 && routeJson.nodeDataArray.length == 0) {
        return this.finishCheck('工艺路线配置不能为空');
      }
      // 获取工站信息
      let nodeInfoList = returnNodeInfoList(routeJson.nodeDataArray, this.sections, this.allActiveStations, this.isAlreadyConfig, this.isGdEditorPage);
      console.log(nodeInfoList, 'returnNodeInfoList:nodeInfoList');

      // 验证开始结束节点,检测连线状态
      if (!verifyNodeFn(routeJson, nodeInfoList)) {
        this.loading = false;
        return false;
      }
      // 处理二次保存问题
      this.handleDuplicateSave(nodeInfoList);

      if (!nodeInfoList || nodeInfoList.length === 0) {
        return this.finishCheck('获取不到配置连接工站');
      }

      // 限制工单工段首尾工序不能设置可跳
      // 工站类型为包装时 包规为必填
      // 工站类型为老化时 老化时间和老化预警时间为必填项且老化预警时间不能大于老化时间
      // 工站类型为组装时  关键料必须配置
      // 工站类型为测试时,标准不良次数必填,不能小于1，且为整数
      if (!verifyStationFn(nodeInfoList)) {
        this.loading = false;
        return false;
      }

      // 验证工段顺序
      if (!verifySectionOrder(nodeInfoList, this.sections)) {
        this.loading = false;
        return false;
      }

      //开线检查设置验证
      let lineInspectionList = this.$refs.workStationInfo.lineInspectionList;
      for (let i = 0; i < lineInspectionList.length; i++) {
        if (lineInspectionList[i].isEnable) {
          let allCheckItemsDisabled = lineInspectionList[i].checkData.every((checkDataItem) => checkDataItem.checkItemList.every((checkItem) => !checkItem.isEnable));
          if (allCheckItemsDisabled) {
            this.$message.error(`开线检查设置中工段${lineInspectionList[i].sectionName}已开启检查，但未启用任何检查项`);
            this.loading = false;
            return;
          }
        }
      }

      let params = {
        routeJson: JSON.stringify(routeJson),
        processRouteList: nodeInfoList
      };

      this.mainParams = this.buildMainParams(params);
      console.log('this.mainParams', this.mainParams);
      // 2待生产/3生产中 允许修改工艺路线 显示修改原因对话框
      // 1：待排程；2：待生产；3：生产中；4：完工；5：锁定；6：强制完工;
      if (this.isGdEditorPage && !this.readOnlyPage && [2, 3].includes(this.workOrderStatus)) {
        this.editCauseDialog.form.reason = '';
        this.editCauseDialog.visible = true;
        return false;
      }

      this.isGdEditorPage ? this.handleProcessWoSubmit(this.mainParams) : this.handleProcessSubmit(this.mainParams);
    },
    // 产品工艺保存
    handleProcessSubmit(params) {
      processSubmit(params)
        .then(async () => {
          this.productData = await this.$store.dispatch('design/getProcessDetail', this.routeQuery.id);
          this.$message.success('工艺路线保存成功');
          // 产品工艺路线 关闭tab页签 跳转到产品工艺页面
          let tag = this.$store.getters.tagList.filter((ele) => ele.value === this.routePath)[0];
          if (tag) {
            this.$store.commit('DEL_TAG', tag);
            this.$refs.topMenu.onReturn();
          }
        })
        .catch((err) => {
          console.log(err);
        })
        .finally(() => {
          this.loading = false;
          this.changeProcessFlag = false;
        });
    },
    // 工单工艺保存
    handleProcessWoSubmit(params) {
      processWoSubmit(params)
        .then(async (res) => {
          let data = res.data.data;
          this.productData = await this.$store.dispatch('design/getProcessWorkRouteByWo', { id: data || this.routeQuery.id });
          this.$message.success('工艺路线保存成功');
        })
        .then(() => {
          if (!this.readOnlyPage) {
            this.$confirm('工单工艺路线改动可能影响工单用料配置，是否前往修改工单用料配置？', '提示', {
              type: 'warning',
              distinguishCancelAndClose: true,
              confirmButtonText: '前往修改',
              cancelButtonText: '取消'
            })
              .then(() => {
                if (this.routePath.endsWith('gdesign')) {
                  let { workOrderId, workOrderNo, status, partMasterId } = this.$route.query;
                  localStorage.setItem('workOrderProcessInfo', JSON.stringify({ id: workOrderId, partMasterId, orderNo: workOrderNo, status: status }));
                  this.$router.replace('/product/workorderRoute');
                }
              })
              .catch(() => {
                this.renderFlow(this.productData, this.isGdEditorPage); // 渲染流程图
              });
          }
        })
        .catch((err) => {
          console.log(err);
        })
        .finally(() => {
          this.loading = false;
          this.changeProcessFlag = false;
        });
    },
    submitProcessMaterialControlList(value) {
      let processId = this.productData.id || this.productData.originalProcessId;
      value.map((v) => (v.processId = processId));
      this.processMaterialControlList = value;
      this.productData.processMaterialControlList = value;
      // this.saveDesigner();
    },
    // 动态改变页面高度
    calculatePageHeight() {
      let that = this;
      window.addEventListener(
        'resize',
        that._throttle(function () {
          that.calculateDesignerBoxHeight();
        }, 500)
      );
    },
    calculateDesignerBoxHeight() {
      let that = this;
      let designerDescriptionDom = document.querySelector('.designer-description');
      if (designerDescriptionDom) {
        let designerDescriptionHeight = designerDescriptionDom.clientHeight;
        if (designerDescriptionHeight < 90) {
          that.designerBoxHeight = `calc(100vh - 220px)`;
        } else if (90 < designerDescriptionHeight && designerDescriptionHeight < 120) {
          that.designerBoxHeight = `calc(100vh - 260px)`;
        } else if (120 < designerDescriptionHeight) {
          that.designerBoxHeight = `calc(100vh - 300px)`;
        }
      }
    },
    handleChangeThumbnail(status) {
      this.thumbnail = status;
      this.$nextTick(() => {
        G(go.Overview, 'overviewSpan', { observed: status ? this._designer.designer : null });
      });
    },
    handleAutoLayout(status) {
      if (status) {
        this._designer.designer.layout = G(go.LayeredDigraphLayout);
      } else {
        this._designer.designer.layout.isOngoing = false;
      }
    },
    dialogSubmit() {
      this.$refs.causeform.submit();
    },
    handleSubmit(form, done) {
      this.mainParams.editReason = form.reason;
      console.log('this.mainParams', this.mainParams);
      processWoSubmit(this.mainParams)
        .then(async () => {
          this.productData = this.isGdEditorPage
            ? await this.$store.dispatch('design/getProcessWorkRouteByWo', { id: this.routeQuery.id })
            : await this.$store.dispatch('design/getProcessDetail', this.routeQuery.id);
          this.$message.success('工艺路线保存成功');
        })
        .then(() => {
          done();
          this.renderFlow(this.productData, this.isGdEditorPage); // 渲染流程图
        })
        .catch((err) => {
          done();
          console.log(err);
        })
        .finally(() => {
          this.editCauseDialog.visible = false;
          this.loading = false;
          this.changeProcessFlag = false;
        });
    },
    handleCauseClose() {
      this.editCauseDialog.visible = false;
      this.loading = false;
      this.changeProcessFlag = false;
    },
    handleChangeStep(variable) {
      let allNodeStations = [defaultStartAndEndNodeData.nodeDataArray[0], ...this.allActiveStations, defaultStartAndEndNodeData.nodeDataArray[1]];
      let designer = this._designer.designer;
      let selectNode = designer.selection.first();
      if (selectNode && selectNode.data.key) {
        let selectNodeIndex = allNodeStations.findIndex((item) => item.key === selectNode.data.key);
        let preNodeKey = allNodeStations[selectNodeIndex + variable].key;
        if (preNodeKey) {
          let node = designer.findNodeForData(designer.model.findNodeDataForKey(preNodeKey));
          designer.select(node);
          this.setcurrentStationInfo(allNodeStations, preNodeKey);
        }
      }
    },
    shrinkStationList() {
      let rowLeftDom = document.querySelector('.orderroute-design .row-left');
      rowLeftDom.classList.toggle('shrink');
    },
    getStationType() {
      getDictionary({ code: 'station_type' }).then((res) => {
        if (res && res.status == 200) {
          this.routeTypes = res.data.data.map((item) => {
            return {
              label: item.dictValue,
              value: item.dictKey
            };
          });
        }
      });
    }
  }
};
</script>
<style scoped lang="scss">
@import './orderroute-design.scss';
</style>

<style lang="scss" scoped>
::v-deep .orderrouteEditCauseDialog {
  .tips {
    color: red;
  }
}
</style>
